{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import bqplot\n",
    "import numpy as np\n",
    "from ipywidgets import link, FloatSlider"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "N = 3 * int(1e5)\n",
    "scale_x = bqplot.LinearScale(min=-5, max=5)\n",
    "scale_y = bqplot.LinearScale(min=-5, max=5)\n",
    "scale_size = bqplot.LinearScale(min=0, max=1)\n",
    "\n",
    "x = np.random.normal(5, 4, N)\n",
    "y = np.random.normal(0, 3, N)\n",
    "\n",
    "size = np.random.rand(N) * 30 + 1\n",
    "\n",
    "scatter = bqplot.ScatterGL(x=x, y=y,\n",
    "                           size=size,\n",
    "                           colors=['red', 'green', 'yellow'],\n",
    "                           scales={\n",
    "                               'x': scale_x, 'y': scale_y, \n",
    "                               'size': scale_size\n",
    "                           },\n",
    "                           default_size=20,\n",
    "                           marker='circle'\n",
    "                          )\n",
    "\n",
    "ax_x = bqplot.Axis(scale=scale_x, grid_lines='solid', label='X')\n",
    "ax_y = bqplot.Axis(scale=scale_y, orientation='vertical', tick_format='0.2f', grid_lines='solid', label='Y')\n",
    "\n",
    "fig = bqplot.Figure(marks=[scatter], axes=[ax_x, ax_y], title='Scatter GL', legend_location='bottom-right', animation_duration=2000)\n",
    "\n",
    "scatter.stroke = 'black'\n",
    "\n",
    "fig"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "N = int(1e4)\n",
    "with scatter.hold_sync():\n",
    "    scatter.x = np.random.normal(5, 4, N)\n",
    "    scatter.y = np.random.normal(0, 3, N)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.colors = ['blue']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.colors = ['blue', 'orange']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.marker = 'cross'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.marker = 'triangle-up'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.marker = 'triangle-down'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.marker = 'square'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "N = 3 * int(1e4)\n",
    "scale_x = bqplot.LinearScale(min=-5, max=5)\n",
    "scale_y = bqplot.LinearScale(min=-5, max=5)\n",
    "scale_size = bqplot.LinearScale(min=0, max=1)\n",
    "scale_color = bqplot.ColorScale(min=0, max=1, scheme='RdYlGn')\n",
    "\n",
    "x = np.random.normal(5, 4, N)\n",
    "y = np.random.normal(0, 3, N)\n",
    "\n",
    "size = np.random.rand(N) * 30 + 1\n",
    "color = np.random.rand(N)\n",
    "\n",
    "scatter = bqplot.ScatterGL(x=x, y=y,\n",
    "                           size=size,\n",
    "                           color=color,\n",
    "                           scales={\n",
    "                               'x': scale_x, 'y': scale_y, \n",
    "                               'size': scale_size, \n",
    "                               'color': scale_color\n",
    "                           },\n",
    "                           default_size=20,\n",
    "                           marker='circle'\n",
    "                          )\n",
    "scatter.selected_style = {'fill': 'blue'}\n",
    "\n",
    "ax_x = bqplot.Axis(scale=scale_x, grid_lines='solid', label='X')\n",
    "ax_y = bqplot.Axis(scale=scale_y, orientation='vertical', tick_format='0.2f', grid_lines='solid', label='Y')\n",
    "\n",
    "fig = bqplot.Figure(marks=[scatter], axes=[ax_x, ax_y], title='Scatter GL', legend_location='bottom-right', animation_duration=2000)\n",
    "\n",
    "panzoom = bqplot.interacts.PanZoom(scales={'x': [scale_x], 'y': [scale_y]})\n",
    "fig.interaction = panzoom\n",
    "\n",
    "scatter.stroke = 'black'\n",
    "\n",
    "fig"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with scatter.hold_sync():\n",
    "    scatter.x = np.random.normal(5, 4, N)\n",
    "    scatter.y = np.random.normal(0, 3, N)\n",
    "    scatter.size = np.random.normal(20, 20, N)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.y = np.random.normal(0, 3, N)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.size = np.random.rand(N) * 50 + 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ipywidgets import FloatSlider, link\n",
    "\n",
    "slider = FloatSlider(min=0.1, max=10., value=scale_color.max)\n",
    "link((slider, 'value'), (scale_color, 'max'))\n",
    "slider"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.stroke = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.stroke_width = 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.x = np.random.normal(5, 4, N)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "input_collapsed": false
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "from bqplot import (\n",
    "    Axis, ColorAxis, LinearScale, DateScale, DateColorScale, OrdinalScale,\n",
    "    OrdinalColorScale, ColorScale, ScatterGL, Lines, Figure, Tooltip, PanZoom\n",
    ")\n",
    "from ipywidgets import Label"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "size = 100\n",
    "price_data = pd.DataFrame(np.cumsum(np.random.randn(150, 2).dot([[1.0, -0.8], [-0.8, 1.0]]), axis=0) + size,\n",
    "                          columns=['Security 1', 'Security 2'], index=pd.date_range(start='01-01-2007', periods=150))\n",
    "\n",
    "np.random.seed(0)\n",
    "x_data = range(size)\n",
    "y_data = np.cumsum(np.random.randn(size) * 100.0)\n",
    "ord_keys = np.array(['A', 'B', 'C', 'D', 'E', 'F'])\n",
    "ordinal_data = np.random.randint(5, size=size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "input_collapsed": false
   },
   "outputs": [],
   "source": [
    "symbols = ['Security 1', 'Security 2']\n",
    "\n",
    "dates_all = price_data.index.values\n",
    "dates_all_t = dates_all[1:]\n",
    "sec1_levels = np.array(price_data[symbols[0]].values.flatten())\n",
    "log_sec1 = np.log(sec1_levels)\n",
    "sec1_returns = log_sec1\n",
    "\n",
    "sec2_levels = np.array(price_data[symbols[1]].values.flatten())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Basic Scatter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import bqplot\n",
    "\n",
    "sc_x = DateScale()\n",
    "sc_y = LinearScale()\n",
    "\n",
    "scatt = ScatterGL(x=dates_all, y=sec2_levels, marker='square', stroke='black', scales={'x': sc_x, 'y': sc_y})\n",
    "ax_x = Axis(scale=sc_x, label='Date')\n",
    "ax_y = Axis(scale=sc_y, orientation='vertical', tick_format='0.0f', label='Security 2')\n",
    "\n",
    "fig = Figure(marks=[scatt], axes=[ax_x, ax_y], animation_duration=5000)\n",
    "\n",
    "panzoom = bqplot.interacts.PanZoom(scales={'x': [sc_x], 'y': [sc_y]})\n",
    "fig.interaction = panzoom\n",
    "\n",
    "fig"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Changing the marker to each point of the scatter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Changing the marker as \n",
    "sc_x = LinearScale()\n",
    "sc_y = LinearScale()\n",
    "\n",
    "scatt = ScatterGL(x=x_data, y=y_data, names=np.arange(10),\n",
    "                scales={'x': sc_x, 'y': sc_y}, colors=['red'], marker='cross')\n",
    "ax_x = Axis(scale=sc_x)\n",
    "ax_y = Axis(scale=sc_y, orientation='vertical', tick_format='0.2f')\n",
    "\n",
    "Figure(marks=[scatt], axes=[ax_x, ax_y], padding_x=0.025)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatt.marker = 'square'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Changing the opacity of each marker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatt.opacities = [0.3, 0.5, 1.]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Representing additional dimensions of data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "input_collapsed": false
   },
   "source": [
    "## Linear Scale for Color Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sc_x = DateScale()\n",
    "sc_y = LinearScale()\n",
    "\n",
    "sc_c1 = ColorScale()\n",
    "scatter = ScatterGL(x=dates_all, y=sec2_levels, color=sec1_returns,\n",
    "                  scales={'x': sc_x, 'y': sc_y, 'color': sc_c1}, \n",
    "                  stroke='black')\n",
    "\n",
    "ax_y = Axis(label='Security 2', scale=sc_y, \n",
    "            orientation='vertical', side='left')\n",
    "\n",
    "ax_x = Axis(label='Date', scale=sc_x, num_ticks=10, label_location='end')\n",
    "ax_c = ColorAxis(scale=sc_c1, tick_format='0.2%', label='Returns', orientation='vertical', side='right')\n",
    "\n",
    "m_chart = dict(top=50, bottom=70, left=50, right=100)\n",
    "\n",
    "Figure(axes=[ax_x, ax_c, ax_y], marks=[scatter], fig_margin=m_chart,\n",
    "       title='Scatter of Security 2 vs Dates')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## setting the fill to be empty\n",
    "scatter.stroke = None\n",
    "scatter.fill = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## Setting the fill back\n",
    "scatter.stroke = 'black'\n",
    "scatter.fill = True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## Changing the color to a different variable\n",
    "scatter.color = sec2_levels\n",
    "ax_c.tick_format = '0.0f'\n",
    "ax_c.label = 'Security 2'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## Changing the range of the color scale\n",
    "sc_c1.colors = ['blue', 'green', 'orange']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Date Scale for Color Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sc_x = LinearScale()\n",
    "sc_y = LinearScale()\n",
    "\n",
    "sc_c1 = DateColorScale(scheme='Reds')\n",
    "scatter = ScatterGL(x=sec2_levels, y=sec1_levels, color=dates_all,\n",
    "                  scales={'x': sc_x, 'y': sc_y, 'color': sc_c1}, default_size=128,\n",
    "                  stroke='black')\n",
    "\n",
    "ax_y = Axis(label='Security 1 Level', scale=sc_y, orientation='vertical', side='left')\n",
    "\n",
    "ax_x = Axis(label='Security 2', scale=sc_x)\n",
    "ax_c = ColorAxis(scale=sc_c1, label='Date', num_ticks=5)\n",
    "\n",
    "m_chart = dict(top=50, bottom=80, left=50, right=50)\n",
    "Figure(axes=[ax_x, ax_c, ax_y], marks=[scatter], fig_margin=m_chart)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "input_collapsed": false
   },
   "source": [
    "## Setting size and opacity based on data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "input_collapsed": false
   },
   "outputs": [],
   "source": [
    "sc_x = LinearScale()\n",
    "sc_y = LinearScale()\n",
    "sc_y2 = LinearScale()\n",
    "\n",
    "sc_size = LinearScale()\n",
    "sc_opacity = LinearScale()\n",
    "\n",
    "\n",
    "scatter2 = ScatterGL(x=sec2_levels, y=sec1_levels, size=sec1_returns,\n",
    "                   scales={'x': sc_x, 'y': sc_y, 'size': sc_size}, \n",
    "                   default_size=128, colors=['orangered'], stroke='black')\n",
    "\n",
    "ax_y = Axis(label='Security 1', scale=sc_y, orientation='vertical', side='left')\n",
    "ax_x = Axis(label='Security 2', scale=sc_x)\n",
    "\n",
    "Figure(axes=[ax_x, ax_y], marks=[scatter2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## Changing the opacity of the scatter\n",
    "scatter2.opacities = [0.5, 0.3, 0.1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## Resetting the opacity and setting the opacity according to the date\n",
    "scatter2.opacities = [1.0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Rotation scale"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sc_x = LinearScale()\n",
    "sc_y = LinearScale()\n",
    "sc_e = LinearScale()\n",
    "sc_c = ColorScale(scheme='Reds')\n",
    "x1 = np.linspace(-1, 1, 250)\n",
    "y1 = np.linspace(-1, 1, 250)\n",
    "x, y = np.meshgrid(x1,y1)\n",
    "x, y = x.flatten(), y.flatten()\n",
    "rot = x**2 + y**2\n",
    "color=x-y\n",
    "scatter = ScatterGL(scales={'x': sc_x, 'y': sc_y, 'color': sc_c, 'rotation': sc_e}, \n",
    "                  x=x, y=y, rotation=rot, color=color,\n",
    "                  stroke=\"black\", stroke_width=20, default_size=200, \n",
    "                  marker='arrow', default_skew=0.5)\n",
    "\n",
    "fig = Figure(marks=[scatter], animation_duration=1000)\n",
    "\n",
    "panzoom = PanZoom(scales={'x': [sc_x], 'y': [sc_y]})\n",
    "fig.interaction = panzoom\n",
    "\n",
    "fig"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.rotation = 1.0 / (x ** 2 + y ** 2 + 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scatter.rotation = x**2 + y**2"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
